Skip to content

feat(Chat): add @ file suggestions to input#27

Merged
remarkablemark merged 4 commits into
masterfrom
feat/suggestions
May 8, 2026
Merged

feat(Chat): add @ file suggestions to input#27
remarkablemark merged 4 commits into
masterfrom
feat/suggestions

Conversation

@remarkablemark
Copy link
Copy Markdown
Member

@remarkablemark remarkablemark commented May 8, 2026

What is the motivation for this pull request?

Add file suggestions in the chat input so users can reference project files quickly with @ mentions in the TUI.

plan.md

What is the current behavior?

The chat input supports slash-command suggestions, but there is no @ mention autocomplete for files.

What is the new behavior?

  • Shows file suggestions below the input when the active token matches @ followed by non-whitespace text.
  • Uses rg --files --hidden -g "!**/.git/**" to load project files with a Node.js directory-walk fallback.
  • Supports Up and Down to change the focused file suggestion.
  • Inserts the focused file path on Tab, replacing the active mention token and appending a trailing space.
  • Preserves existing slash-command behavior and keeps Enter as submit.
  • Adds focused tests for file suggestions and input interaction.
  • Includes a small grepSearch cleanup changing results.length === 0 to !results.length.

Checklist:

File Suggestions For `@` Mentions In Chat Input

Summary:

Add file-path suggestions to the chat input when the active token matches `@` followed by at least one non-whitespace character. Show suggestions below the input, allow `↑`/`↓` navigation, and on `Tab` replace the active `@query` token with the selected file path plus one trailing space. Use `ripgrep` first to gather project files, with a Node.js recursive fallback similar to `grepSearch()`.

Key Changes:

- Update `src/components/Chat/Input.tsx` to:
  - keep owning the input string and reset/remount behavior for `TextInput`
  - detect file suggestion mode from the active token using `(^|\s)@\S+`
  - render `FileSuggestions` only when slash-command mode is not active
  - apply the callback result from `FileSuggestions` by replacing the input value and remounting `TextInput`
- Add `src/components/Chat/FileSuggestions.tsx` to own:
  - extraction of the active `@query` from the provided input value
  - project file discovery
  - filtering and focused-index navigation
  - `Tab` confirmation
  - rendering the suggestion list below the input with at most `5` visible options
- Keep slash command behavior unchanged:
  - if input starts with `/`, continue rendering `CommandMenu`
  - file suggestions do not appear while slash-command mode is active
  - `Enter` continues to submit the input normally; it does not confirm file suggestions
- Implement file discovery inside `FileSuggestions.tsx` using:
  - first choice: `rg --files` from `process.cwd()`
  - fallback: recursive `readdirSync(..., { withFileTypes: true })`
  - normalization to relative paths with `/` separators
  - include hidden files/directories in suggestions
  - exclude only `.git` from the fallback traversal
- Keep matching simple and case-insensitive against the path text after `@`.
- Have `FileSuggestions` call `onSelect(nextInput: string)` so it returns the fully rewritten input string, including the trailing space, instead of only the raw file path.
- Do not support `Esc` dismissal for file suggestions; the list should open and close solely based on the current input text and normal editing.

Public Interfaces / Behavior:

- No CLI/API changes.
- New TUI behavior:
  - typing `@` followed by any non-whitespace character in the active token opens file suggestions below the input
  - `↑`/`↓` move focus through suggestions
  - `Tab` inserts the focused file path into the input and appends one space
  - `Enter` still submits the current input and does not confirm the suggestion list
  - suggestions disappear automatically when the active token no longer matches `@\S+` or when no files match

Test Plan:

- Add `Input` tests for:
  - no file suggestions for plain text or bare `@`
  - file suggestions appear for `@s`, `@1`, `@_`, or `@foo-bar`
  - slash command suggestions still win for leading `/`
  - `Tab` inserts the focused file path and appends one trailing space
  - insertion replaces only the active trailing `@query` token and preserves surrounding text
  - `Enter` still submits while file suggestions are visible
  - `Backspace` updates or closes file suggestions correctly
  - disabled input ignores file suggestion interactions
- Add `FileSuggestions` tests for:
  - `rg --files` success path
  - fallback to Node.js traversal when `rg` fails
  - fallback excludes `.git` but includes other hidden paths
  - case-insensitive filtering
  - focused-index movement and `Tab` selection behavior
  - max visible option count is `5`

Assumptions:

- Suggestion source is project file paths relative to the current working directory.
- `ripgrep` is optional; the feature must work without it via the Node.js fallback.
- `FileSuggestions` will contain both its own logic and rendering; no separate helper module is introduced initially.
- The input remains synchronized by remounting `TextInput` with a refreshed `defaultValue` after a selection is inserted.
In `FileSuggestions.tsx`, `isMounted` only prevents this sequence:

1. component starts async file loading
2. component unmounts
3. async load resolves
4. `setFilePaths(...)` runs after unmount

In modern React, that usually won’t break correctness here, but it can still be noisy and it is
unnecessary work. Since this effect is a one-shot async read, the guard is a simple way to avoid
updating dead state.

That said, for this specific component:

- there is no subscription to clean up
- there is no retry loop
- there is no race between multiple concurrent requests
- the only real concern is post-unmount setState

So if you want to simplify, removing `isMounted` is reasonable. The behavior of the feature would still be
fine. I’d only keep it if you want to be explicit about ignoring late async results.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
src/components/Chat/FileSuggestions.tsx 100.00% <100.00%> (ø)
src/components/Chat/Input.tsx 100.00% <100.00%> (ø)
src/utils/tools.ts 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@remarkablemark remarkablemark self-assigned this May 8, 2026
@remarkablemark remarkablemark changed the title feat(Chat): add @ file suggestions to input feat(Chat): add @ file suggestions to input May 8, 2026
@remarkablemark remarkablemark added the enhancement New feature or request label May 8, 2026
@remarkablemark remarkablemark merged commit 873cb5a into master May 8, 2026
15 checks passed
@remarkablemark remarkablemark deleted the feat/suggestions branch May 8, 2026 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant